<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>HTML5 Three.js 3D人偶玩具自动化生产车间动画</title>
<style>
html,
body {
    margin: 0;
    overflow: hidden;
    height: 100%;
    width: 100%;
}
</style>

</head>

<body>
<script src="js/three.min.js"></script>
<script src="js/TweenMax.min.js"></script>
<script>
"use strict";
console.clear();
TweenMax.lagSmoothing(0);
THREE.ImageUtils.crossOrigin = '';
var colors = {
    blue: '#4281A4',
    green: '#48A9A6',
    background: '#D0CBC7',
    ground: '#E4DFDA',
    yellow: '#D4B483',
    red: '#C1666B',
    lid: '#B05D62',
    skin: '#F5D6BA'
};
var settings = {
    openSpeed: 0.8
};
var Utils = {
    degToRad: function(degrees) {
        return degrees * Math.PI / 180;
    }
};
var Stage = (function() {
    function Stage() {
        // container
        this.render = function() {
            this.renderer.render(this.scene, this.camera);
        };
        this.add = function(elem) {
            this.scene.add(elem);
        };
        this.remove = function(elem) {
            this.scene.remove(elem);
        };
        this.container = document.createElement('div');
        document.body.appendChild(this.container);
        // renderer
        this.renderer = new THREE.WebGLRenderer({
            antialias: true,
            alpha: false
        });
        this.renderer.setSize(window.innerWidth, window.innerHeight);
        this.renderer.setClearColor(colors.background, 1);
        this.renderer.shadowMap.enabled = true;
        this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
        this.container.appendChild(this.renderer.domElement);
        // scene
        this.scene = new THREE.Scene();
        //this.scene.fog = new THREE.Fog( colors.ground, 0, 10);
        // camera
        var aspect = window.innerWidth / window.innerHeight;
        var d = 20;
        this.camera = new THREE.OrthographicCamera(-d * aspect, d * aspect, d, -d, -100, 1000);
        this.camera.position.x = 30;
        this.camera.position.y = 10;
        this.camera.position.z = -10;
        this.camera.lookAt(new THREE.Vector3(0, 5, 0));
        //light
        this.light = new THREE.DirectionalLight(0xffffff, 0.5);
        this.light.castShadow = true;
        this.light.position.set(8, 15, -5);
        this.scene.add(this.light);
        this.softLight = new THREE.AmbientLight(0xffffff, 0.5);
        this.scene.add(this.softLight);
        // floor
        var width = 500;
        var depth = 1000;
        var geometry = new THREE.PlaneGeometry(depth, width);
        var material = new THREE.MeshBasicMaterial({
            color: colors.ground,
            shading: THREE.FlatShading
        });
        var plane = new THREE.Mesh(geometry, material);
        plane.rotation.x = -Utils.degToRad(90); //1.57079633;
        plane.position.y = 0;
        plane.position.z = -width / 2;
        this.floor = new THREE.Group();
        this.floor.add(plane);
        this.scene.add(this.floor);
        // group
        this.group = new THREE.Group();
        this.scene.add(this.group);
    }
    return Stage;
}());
var Box = (function() {
    function Box() {
        this.openAnimation = new TimelineMax();
        this.closeAnimation = new TimelineMax();
        this.dropAnimation = new TimelineMax();
        this.fallAnimation = new TimelineMax();
        this.setAnimation = function() {
            var _this = this;
            var speed = 1;
            var boxBounceSpeed = speed / 3;
            this.openAnimation.clear();
            this.openAnimation.stop();
            this.openAnimation.to(this.group.position, boxBounceSpeed, {
                y: 4,
                delay: 0,
                ease: Power2.easeInOut
            });
            this.openAnimation.to(this.group.position, boxBounceSpeed * 2, {
                y: 0,
                x: 0,
                z: 0,
                ease: Bounce.easeOut
            });
            this.openAnimation.to(this.lid.rotation, speed, {
                z: 2,
                ease: Bounce.easeOut
            }, 0);
            this.openAnimation.to(this.crank.rotation, speed * 3, {
                z: Utils.degToRad(180),
                ease: Elastic.easeOut
            }, 0);
            // -----
            this.crankSpeed = 0;
            this.crankAnimation = setInterval(function() {
                _this.moveCrank();
            }, 20);
            // -----
            this.dropAnimation.clear();
            this.dropAnimation.stop();
            this.dropAnimation.to(this.group.position, 1, {
                y: 0,
                delay: 0.5,
                ease: Bounce.easeOut
            });
            // -----
            this.fallAnimation.clear();
            this.fallAnimation.stop();
            this.fallAnimation.to(this.group.position, 1, {
                y: -20,
                delay: 0.2,
                ease: Power3.easeIn
            });
            this.fallAnimation.to(this.group.rotation, 1, {
                x: Utils.degToRad(120),
                delay: 0.2,
                ease: Power3.easeIn
            }, 0);
        };
        this.moveCrank = function() {
            if (this.closed) {
                this.crank.rotation.z = this.crank.rotation.z > Utils.degToRad(360) ? 0 : this.crank.rotation.z + this.crankSpeed;
                if (this.crankSpeed < 0.1)
                    this.crankSpeed += 0.005;
            }
        };
        this.add = function(elem) {
            this.group.add(elem);
        };
        this.stopAnimations = function() {
            this.openAnimation.stop();
            this.closeAnimation.stop();
        };
        this.open = function(skipAnimation) {
            if (skipAnimation === void 0) {
                skipAnimation = false;
            }
            this.closed = false;
            //this.stopAnimations();
            this.openAnimation.duration(skipAnimation ? 0.1 : 3);
            this.openAnimation.restart();
        };
        this.close = function() {
            this.closed = true;
            //this.stopAnimations();
            this.closeAnimation.duration(3);
            this.closeAnimation.restart();
        };
        this.drop = function(skipAnimation) {
            if (skipAnimation === void 0) {
                skipAnimation = false;
            }
            this.dropAnimation.duration(skipAnimation ? 0.1 : 1);
            this.dropAnimation.restart();
        };
        this.fall = function(skipAnimation) {
            if (skipAnimation === void 0) {
                skipAnimation = false;
            }
            this.fallAnimation.duration(skipAnimation ? 0.1 : 1);
            this.fallAnimation.restart();
        };
        this.closed = true;
        this.group = new THREE.Group();
        var material = new THREE.MeshToonMaterial({
            color: colors.red
        });
        var geometry = new THREE.BoxGeometry(4, 1, 4);
        var boxBottom = new THREE.Mesh(geometry, material);
        boxBottom.position.y = 0.5;
        //boxBottom.castShadow = true;
        //boxBottom.receiveShadow = true;
        var geometry = new THREE.BoxGeometry(6, 1, 6);
        var boxBack = new THREE.Mesh(geometry, material);
        boxBack.position.y = 2.5;
        boxBack.position.x = -2.5;
        boxBack.rotation.z = Utils.degToRad(90);
        //boxBack.castShadow = true;
        //boxBack.receiveShadow = true;
        var geometry = new THREE.BoxGeometry(6, 1, 6);
        var boxFront = new THREE.Mesh(geometry, material);
        boxFront.position.y = 2.5;
        boxFront.position.x = 2.5;
        boxFront.rotation.z = Utils.degToRad(90);
        //boxFront.castShadow = true;
        //boxFront.receiveShadow = true;
        var geometry = new THREE.BoxGeometry(4, 1, 6);
        var boxLeft = new THREE.Mesh(geometry, material);
        boxLeft.position.y = 2.5;
        boxLeft.position.z = 2.5;
        boxLeft.rotation.x = Utils.degToRad(90);
        //boxLeft.castShadow = true;
        //boxLeft.receiveShadow = true;
        var geometry = new THREE.BoxGeometry(4, 1, 6);
        var boxRight = new THREE.Mesh(geometry, material);
        boxRight.position.y = 2.5;
        boxRight.position.z = -2.5;
        boxRight.rotation.x = Utils.degToRad(90);
        //boxRight.castShadow = true;
        //boxRight.receiveShadow = true;
        var geometry = new THREE.BoxGeometry(6, 1.75, 6);
        geometry.applyMatrix(new THREE.Matrix4().makeTranslation(3, 1, 0));
        var material = new THREE.MeshToonMaterial({
            color: colors.lid
        });
        this.lid = new THREE.Mesh(geometry, material);
        this.lid.position.y = 5.4;
        this.lid.position.x = -3;
        //this.lid.castShadow = true;
        //this.lid.receiveShadow = true;
        this.group.add(this.lid);
        this.group.add(boxBottom);
        this.group.add(boxBack);
        this.group.add(boxLeft);
        this.group.add(boxRight);
        this.group.add(boxFront);
        this.crank = new THREE.Group();
        var geometry = new THREE.CylinderGeometry(0.3, 0.3, 0.6, 8);
        var material = new THREE.MeshToonMaterial({
            color: colors.yellow
        });
        var axel = new THREE.Mesh(geometry, material);
        axel.rotation.x = Utils.degToRad(90);
        //axel.castShadow = true;
        //axel.receiveShadow = true;
        var geometry = new THREE.BoxGeometry(1, 0.3, 3, 8);
        var material = new THREE.MeshToonMaterial({
            color: colors.yellow
        });
        var shaft = new THREE.Mesh(geometry, material);
        shaft.position.y = 1;
        shaft.rotation.x = Utils.degToRad(90);
        //shaft.castShadow = true;
        //shaft.receiveShadow = true;
        var geometry = new THREE.CylinderGeometry(0.5, 0.5, 1, 8);
        var material = new THREE.MeshToonMaterial({
            color: colors.yellow
        });
        var handle = new THREE.Mesh(geometry, material);
        handle.position.z = -0.6;
        handle.position.y = 2;
        handle.rotation.x = Utils.degToRad(90);
        //handle.castShadow = true;
        //handle.receiveShadow = true;
        this.crank.add(axel);
        this.crank.add(shaft);
        this.crank.add(handle);
        this.crank.position.z = -3.5;
        this.crank.position.y = 3.5;
        this.crank.rotation.z = Utils.degToRad(Math.random() * 360);
        this.group.add(this.crank);
        this.group.position.y = 20;
        this.setAnimation();
    }
    return Box;
}());
var Jack = (function() {
    function Jack(color, face) {
        this.openAnimation = new TimelineMax();
        this.closeAnimation = new TimelineMax();
        this.moveAnimation = new TimelineMax();
        this.setAnimation = function() {
            var speed = 1;
            // open animation
            this.openAnimation.clear();
            this.openAnimation.stop();
            var jackDelay = 0.2;
            this.openAnimation.to(this.group.position, speed * 2, {
                y: 5,
                ease: Elastic.easeOut
            }, jackDelay);
            this.openAnimation.to(this.leftHand.position, speed * 2, {
                z: -2.1,
                y: 3.8,
                ease: Elastic.easeOut
            }, jackDelay);
            this.openAnimation.to(this.rightHand.position, speed * 2, {
                z: 2.1,
                y: 3.8,
                ease: Elastic.easeOut
            }, jackDelay);
            this.openAnimation.to(this.group.rotation, speed / 3, {
                x: Math.random() - 0.5,
                z: Math.random() - 0.5,
                ease: Power3.easeInOut
            }, jackDelay);
            this.openAnimation.to(this.group.rotation, speed * 4, {
                x: 0,
                z: (Math.random() / 10) - 0.1,
                ease: Elastic.easeOut
            }, speed / 3);
            this.openAnimation.to(this.head.position, speed * 3, {
                y: 6,
                ease: Elastic.easeOut
            }, jackDelay);
            // move animation
            this.moveAnimation.clear();
            this.moveAnimation.stop();
            this.moveAnimation.to(this.group.rotation, 0.6, {
                x: -0.5,
                ease: Power3.easeIn
            }, 0);
            this.moveAnimation.to(this.group.rotation, speed * 2, {
                x: 0,
                ease: Elastic.easeOut
            });
        };
        this.stopAnimations = function() {
            this.openAnimation.pause();
            this.closeAnimation.pause();
            this.moveAnimation.pause();
        };
        this.open = function(skipAnimation) {
            if (skipAnimation === void 0) {
                skipAnimation = false;
            }
            this.openAnimation.duration(skipAnimation ? 0.1 : 3);
            this.openAnimation.restart();
        };
        this.close = function() {
            //this.stopAnimations();
            //this.closeAnimation.duration(6);
            this.closeAnimation.restart();
        };
        this.move = function(speed) {
            this.moveAnimation.restart();
        };
        this.group = new THREE.Group();
        var geometry = new THREE.CylinderGeometry(1.1, 1.3, 2.5, 15);
        var material = new THREE.MeshToonMaterial({
            color: color
        });
        this.body = new THREE.Mesh(geometry, material);
        this.body.position.y = 2.5;
        //this.body.castShadow = true;
        //this.body.receiveShadow = true;
        var material = new THREE.MeshToonMaterial({
            color: colors.skin,
            map: face
        });
        var geometry = new THREE.SphereGeometry(1.7, 32, 32);
        this.head = new THREE.Mesh(geometry, material);
        this.head.position.y = 4;
        //this.head.castShadow = true;
        //this.head.receiveShadow = true;
        var material = new THREE.MeshToonMaterial({
            color: colors.skin
        });
        var geometry = new THREE.SphereGeometry(0.5, 32, 32);
        this.leftHand = new THREE.Mesh(geometry, material);
        this.leftHand.position.z = -1.5;
        this.leftHand.position.y = 2;
        //this.leftHand.castShadow = true;
        //this.leftHand.receiveShadow = true;
        var geometry = new THREE.SphereGeometry(0.5, 32, 32);
        this.rightHand = new THREE.Mesh(geometry, material);
        this.rightHand.position.z = 1.5;
        this.rightHand.position.y = 2;
        //this.rightHand.castShadow = true;
        //this.rightHand.receiveShadow = true;
        this.group.add(this.body);
        this.group.add(this.head);
        this.group.add(this.leftHand);
        this.group.add(this.rightHand);
        this.setAnimation();
    }
    return Jack;
}());
var Dispenser = (function() {
    function Dispenser() {
        this.openAnimation = new TimelineMax();
        this.setAnimation = function() {
            this.openAnimation.clear();
            this.openAnimation.stop();
            this.openAnimation.fromTo(this.lidRight.rotation, 1, {
                x: Utils.degToRad(0)
            }, {
                x: Utils.degToRad(-90),
                ease: Elastic.easeOut
            }, 0);
            this.openAnimation.fromTo(this.lidLeft.rotation, 1, {
                x: Utils.degToRad(0)
            }, {
                x: Utils.degToRad(90),
                ease: Elastic.easeOut
            }, 0);
            this.openAnimation.fromTo(this.lidRight.rotation, 0.5, {
                x: Utils.degToRad(-90)
            }, {
                x: Utils.degToRad(0),
                ease: Power3.easeInOut
            }, 1.5);
            this.openAnimation.fromTo(this.lidLeft.rotation, 0.5, {
                x: Utils.degToRad(90)
            }, {
                x: Utils.degToRad(0),
                ease: Power3.easeInOut
            }, 1.5);
        };
        this.open = function() {
            this.openAnimation.restart();
        };
        this.group = new THREE.Group();
        var geometry = new THREE.BoxGeometry(10, 30, 10);
        geometry.applyMatrix(new THREE.Matrix4().makeTranslation(0, 15, 0));
        var material = new THREE.MeshToonMaterial({
            color: '#eeeeee'
        });
        this.tube = new THREE.Mesh(geometry, material);
        this.group.add(this.tube);
        var geometry = new THREE.BoxGeometry(10, 1, 5);
        geometry.applyMatrix(new THREE.Matrix4().makeTranslation(0, -0.5, 2.5));
        var material = new THREE.MeshToonMaterial({
            color: '#dddddd'
        });
        this.lidLeft = new THREE.Mesh(geometry, material);
        this.group.add(this.lidLeft);
        var geometry = new THREE.BoxGeometry(10, 1, 5);
        geometry.applyMatrix(new THREE.Matrix4().makeTranslation(0, -0.5, -2.5));
        var material = new THREE.MeshToonMaterial({
            color: '#dddddd'
        });
        this.lidRight = new THREE.Mesh(geometry, material);
        this.group.add(this.lidRight);
        this.lidLeft.position.z = -5;
        this.lidLeft.rotation.x = Utils.degToRad(90);
        this.lidRight.position.z = 5;
        this.lidRight.rotation.x = Utils.degToRad(-90);
        this.setAnimation();
    }
    return Dispenser;
}());
var App = (function() {
    function App(count) {
        if (count === void 0) {
            count = 5;
        }
        this.time = 4;
        this.count = 0;
        this.tick = function() {
            var _this = this;
            this.stage.render();
            requestAnimationFrame(function() {
                _this.tick();
            });
        };
        this.addJack = function(skipAnimation) {
            if (skipAnimation === void 0) {
                skipAnimation = false;
            }
            var jack = new Jack(this.colorChoices[Math.floor(Math.random() * this.colorChoices.length)], this.face);
            var box = new Box();
            var group = new THREE.Group();
            group.position.z = Math.floor(this.count / 2) * -15;
            box.add(jack.group);
            group.add(box.group);
            this.jacks.push({
                box: box,
                jack: jack,
                group: group
            });
            this.stage.add(group);
            box.drop(skipAnimation);
            this.dispenser.open();
        };
        this.move = function(skipAnimation) {
            var _this = this;
            if (skipAnimation === void 0) {
                skipAnimation = false;
            }
            while (this.jacks.length >= this.count) {
                var removed = this.jacks.shift();
                if (removed)
                    this.stage.remove(removed.group);
            }
            var _loop_1 = function(i) {
                if (this_1.jacks[i]) {
                    box = this_1.jacks[i].box;
                    jack = this_1.jacks[i].jack;
                    group = this_1.jacks[i].group;
                    if (!box.closed)
                        this_1.jacks[i].jack.move(2.2);
                    if (i <= Math.floor(this_1.count / 2) && box.closed) {
                        if (i != Math.floor(this_1.count / 2)) {
                            this_1.jacks[i].box.open(true);
                            this_1.jacks[i].jack.open(true);
                        } else
                            setTimeout(function() {
                                _this.jacks[i].box.open();
                                _this.jacks[i].jack.open();
                            }, 1000);
                    }
                    if (i == 0) {
                        this_1.jacks[i].box.fall(skipAnimation);
                    }
                    TweenMax.to(group.position, skipAnimation ? 0 : 1, {
                        z: (Math.floor(this_1.count / 2) - i) * 15,
                        ease: Power3.easeInOut
                    });
                }
            };
            var this_1 = this,
                box, jack, group;
            for (var i = this.jacks.length - 1; i >= 0; i--) {
                _loop_1(i);
            }
            this.addJack();
            setTimeout(function() {
                _this.move();
            }, this.time * 1000);
        };
        this.count = count;
        this.jacks = [];
        this.face = THREE.ImageUtils.loadTexture('');
        //this.beltTexture = THREE.ImageUtils.loadTexture('');
        this.colorChoices = [colors.blue]; //, colors.green, colors.yellow];
        this.stage = new Stage();
        this.stage.floor.position.z = (Math.floor(this.count / 2) * 15) - 8;
        this.stage.floor.position.y = -1.5;
        this.dispenser = new Dispenser();
        this.dispenser.group.position.y = 16;
        this.dispenser.group.position.z = Math.floor(this.count / 2) * -15;
        this.stage.add(this.dispenser.group);
        var width = this.count * 20;
        var depth = 30;
        var geometry = new THREE.PlaneGeometry(depth, width);
        var material = new THREE.MeshBasicMaterial({
            color: '#777777',
            shading: THREE.FlatShading
        });
        //this.beltTexture.repeat.y = 100;
        //this.beltTexture.wrapS = this.beltTexture.wrapT = THREE.RepeatWrapping;
        //this.beltTexture.repeat.set( depth / 8, width / 8 );
        var plane = new THREE.Mesh(geometry, material);
        plane.rotation.x = -Utils.degToRad(90); //1.57079633;
        plane.position.y = -1;
        plane.position.z = -width / 2;
        this.belt = new THREE.Group();
        this.belt.add(plane);
        this.stage.add(this.belt);
        this.belt.position.z = -Math.floor(this.count / 2) * -11;
        this.tick();
        while (this.jacks.length < this.count) {
            this.addJack(true);
        }
        this.move(true);
    }
    return App;
}());
var app = new App(5);
</script>
</body>
</html>